{% import 'path_utils.jinja' as path_utils with context %}

{% set name = properties["name"] %}
{% set deployment = properties["deployment"] %}
{% set image = properties["image"] %}
{% set zone = properties["zone"] %}
{% set sub_zone = path_utils.zoneToRegion(zone) %}
{% set network = path_utils.networkPath(properties["network"]) %}
{% set subnetwork = path_utils.subnetworkPath(zone, properties["subnetwork"]) %}
{% set networkIP = properties["networkIP"] %}
{% set machineType = path_utils.machineTypePath(zone, properties["machineType"]) %}
{% set routeIP = properties["routeIP"] %}
{% set listnerIP = properties["listnerIP"] %}
{% set bootDiskSizeGb = properties["bootDiskSizeGb"] %}
{% set bootDiskType = path_utils.diskTypePath(zone, properties["bootDiskType"]) %}

{% set package = "mssql-db" %}
{% set adHost = properties["adHost"] %}
{% set allNodes = properties["allNodes"] %}
{% set domainDNSName = properties["domainDNSName"] %}
{% set sequence = properties["sequence"] %}
{% set saAccount = properties["saAccount"] %}
{% set saPassword = properties["saPassword"] %}
{% set saSQLPassword = properties["saSQLPassword"] %}

{% set statusConfigUrl = properties["statusConfigUrl"] %}
{% set statusVariablePath = properties["statusVariablePath"] %}
{% set statusUptimeDeadline = properties["statusUptimeDeadline"] %}


resources:
  - name: {{ name }}
    type: compute.v1.instance
    properties:
      zone: {{ zone }}
      machineType: {{ machineType }}
      canIpForward: true
      disks:
      {# Request boot disk creation (mark for auto delete)#}
      - deviceName: boot
        type: PERSISTENT
        boot: true
        autoDelete: true
        initializeParams:
          sourceImage: {{ image }}
          diskType: {{ bootDiskType }}
          diskSizeGb: {{ bootDiskSizeGb }}
      networkInterfaces:
      - network: {{ network }}
        accessConfigs:
        - name: External NAT
          type: ONE_TO_ONE_NAT
        subnetwork: {{ subnetwork }}
        networkIP: {{ networkIP }}
      tags:
        items:
          - {{ package }}
          - {{ deployment }}-tcp-3389
          - {{ deployment }}-tcp-1433
          - {{ deployment }}-tcp-5022
      serviceAccounts:
        - email: default
          scopes:
            - 'https://www.googleapis.com/auth/cloud-platform'
            - 'https://www.googleapis.com/auth/cloudruntimeconfig'
            - 'https://www.googleapis.com/auth/devstorage.read_write'
      metadata:
        dependsOn:
        - {{ adHost }}
        - {{ subnetwork }}
        - $(ref.{{ deployment }}-ad-waiter.name)
        items:
        - key: domain-dns-name
          value: {{ domainDNSName }}
        - key: service-account-name
          value: {{ saAccount }}
        - key: service-account-password
          value: {{ saPassword }}
        - key: sql-sa-password
          value: {{ saSQLPassword }}
        - key: status-config-url
          value: {{ statusConfigUrl }}
        - key: status-variable-path
          value: {{ statusVariablePath }}{{ sequence }}
        - key: status-uptime-deadline
          value: {{ statusUptimeDeadline }}
        - key: sql-nodes
          value: {{ allNodes }}
        - key: windows-startup-script-ps1
          value: |
            Set-StrictMode -Version Latest

            $script:gce_install_dir = 'C:\Program Files\Google\Compute Engine\sysprep'

            # Import Modules
            try {
                Import-Module $script:gce_install_dir\gce_base.psm1 -ErrorAction Stop
            }
            catch [System.Management.Automation.ActionPreferenceStopException] {
                Write-Host $_.Exception.GetBaseException().Message
                Write-Host ("Unable to import GCE module from $script:gce_install_dir. " +
                    'Check error message, or ensure module is present.')
                exit 2
            }

            # Default Values
            $Script:c2d_scripts_bucket = 'c2d-windows/scripts'
            $Script:install_path="C:\C2D" # Folder for downloads
            $script:show_msgs = $false
            $script:write_to_serial = $false


            # Functions
            function DownloadScript {
                <#
                .SYNOPSIS
                    Downloads a script to the localmachine from GCS.
                .DESCRIPTION
                    Uses WebClient to download a script file.
                .EXAMPLE
                     DownloadScript -path bucket/.. -filename <name>
                #>
                param (
                [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
                    $path,
                [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
                    $filename,
                [Switch] $overwrite
                )
                $storage_url = 'http://storage.googleapis.com'
                $download_url = "$storage_url/$path"


                # Check if file already exists and act accordingly.
                if ((Test-path -path $filename)){
                  if ($overwrite){
                    Write-Log "$filename already exists. Overwrite flag set."
                    _DeleteFiles -files $filename
                  }
                  else {
                    Write-Log "$filename already exists. Overwrite flag notset."
                    return $true
                  }
                }
                # Download the file
                Write-Log "Original download url: $download_url"
                # To avoid cache issues
                $url = $download_url + "?random=" + (Get-Random).ToString()

                Write-Log "Downloading $url to $filename"
                try {
                  Invoke-WebRequest -Uri $url -OutFile $filename -Headers @{"Cache-Control"="private"}
                }
                catch [System.Net.WebException] {
                  $response = $_.Exception.Response
                  if ($response) {
                    _PrintError
                    Write-Log $response.StatusCode -error # This is a System.Net.HttpStatusCode enum value
                    Write-Log $response.StatusCode.value__ -error # This is the numeric version.
                  }
                  else {
                    $type = $_.Exception.GetType().FullName
                    $message = $_.Exception.Message
                    Write-Log "$type $message"
                  }
                  return $false
                }

                # Check if download successfull
                if ((Test-path -path $filename)){
                  return $true
                }
                else {
                  Write-Log "File not found."
                  return $false
                }
            }


            ## Main
            # Instance specific variables
            $script_name = 'sql_install_light.ps1'
            $script_subpath = 'sqlserver'
            $task_name = "SQLInstall"

            # Create the C:\C2D folder
            if (!(Test-path -path $Script:install_path )) {
              try {
                New-Item -ItemType directory -Path $Script:install_path
              }
              catch {
                _PrintError
                exit 1
              }
            }

            # Download the scripts
            # Base Script
            $base_script_path = "$Script:c2d_scripts_bucket/c2d_base.psm1"
            $base_script = "$Script:install_path\c2d_base.psm1"
            if (DownloadScript -path $base_script_path -filename $base_script) {
              Write-Log "File downloaded successfully."
            }
            else {
              Write-Log "File not found."
              exit 2
            }
            # Run Script
            $run_script = "$Script:install_path\$script_name"
            $run_script_path = "$Script:c2d_scripts_bucket/$script_subpath/$script_name"
            if (DownloadScript -path $run_script_path -filename $run_script) {
              Write-Log "File downloaded successfully."
            }
            else {
              Write-Log "File not found."
              exit 2
            }


            # Execute the script
            Write-Log "Checking if $task_name schtask exists?"
            $sc_task = Get-ScheduledTask -TaskName $task_name -ErrorAction SilentlyContinue
            if ($sc_task) {
              Write-Log "$task_name schtask exists."
              try {
                Write-Log "-- Executing schtask $task_name. --"
                $response = Start-ScheduledTask -TaskName $task_name
                Write-Log $response

              }
              catch {
                $type = $_.Exception.GetType().FullName
                $message = $_.Exception.Message
                Write-Log "$type $message"
                exit 1
              }
            }
            else {
              Write-Log "schtask $task_name does not exists."
              Write-Log "Executing: $run_script"
              try {
                & $run_script -task_name $task_name
              }
              catch {
                $type = $_.Exception.GetType().FullName
                $message = $_.Exception.Message
                Write-Log "$type $message"
                exit 1
              }
            }

  # Creates Routes
  - name: {{ name }}-route
    type: compute.v1.route
    properties:
      destRange: {{ routeIP }}/32
      network: {{ network }}
      nextHopInstance: $(ref.{{ name }}.selfLink)
      nextHopInstanceZone: {{ zone }}
      priority: 1
      tags: []
    metadata:
      dependsOn:
      - {{ name }}

  - name: {{ name }}-route-listner
    type: compute.v1.route
    properties:
      destRange: {{ listnerIP }}/32
      network: {{ network }}
      nextHopInstance: $(ref.{{ name }}.selfLink)
      nextHopInstanceZone: {{ zone }}
      priority: 1
      tags: []
    metadata:
      dependsOn:
      - {{ name }}
  - name: {{ deployment }}-sql-waiter-{{ sequence }}
    type: runtimeconfig.v1beta1.waiter
    properties:
      parent: $(ref.{{ deployment }}-config.name)
      waiter: sql-waiter
      timeout: {{ statusUptimeDeadline }}s
      success:
        cardinality:
          path: {{ statusVariablePath }}{{ sequence }}/success
          number: 1.0
      failure:
        cardinality:
          path: {{ statusVariablePath }}{{ sequence }}/failure
          number: 1.0
    metadata:
      dependsOn:
      - {{ name }}
